package org.miniframework.aop;

import org.miniframework.aop.annotation.Aspect1;
import org.miniframework.aop.annotation.Order;
import org.miniframework.aop.aspect.AspectInfo1;
import org.miniframework.aop.aspect.DefaultAspect;
import org.miniframework.core.BeanContainer;
import org.miniframework.util.ValidationUtil;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * AOP 1.0(不支持表达式)
 */
@Deprecated
public class AspectWeaver1 {

    private BeanContainer beanContainer;

    public AspectWeaver1(){
        this.beanContainer = BeanContainer.getInstance();
    }

    public void doAop(){
        // 1.获取所有的切面类
        Set<Class<?>> aspectSet = beanContainer.getClassesByAnnotation(Aspect1.class);
        // 2.将切面类按照不同的拦截controller目前进行切分
        Map<Class<? extends Annotation>, List<AspectInfo1>> categorizedMap = new HashMap<>();
        if (ValidationUtil.isEmpty(aspectSet)){return;}
        for (Class<?> aspectClass : aspectSet){
            if (verifyAspect(aspectClass)){
                categorizeAspect(categorizedMap,aspectClass);
            }else {
                throw new RuntimeException("@Aspect and @Order have not been added to the Aspect class, or Aspect class does not extend from DefaultAspect or the value in Aspect Tag equels @Aspect");
            }
        }
        // 3.按照不同的拦截controller 分别去执行 Aspect的逻辑
        if (ValidationUtil.isEmpty(categorizedMap)){return;}
        for (Class<? extends Annotation> category : categorizedMap.keySet()){
            weaveByCategory(category,categorizedMap.get(category));
        }
    }

    // 循环执行 aspect
    private void weaveByCategory(Class<? extends Annotation> category, List<AspectInfo1> aspectInfo1List) {
        // 1.获取被代理类的集合
        Set<Class<?>> classSet = beanContainer.getClassesByAnnotation(category);
        if (ValidationUtil.isEmpty(classSet)){return;}
        // 2.遍历被代理类，分别为每个代理类生成动态代理实例
        for (Class<?> tagetClass : classSet){
            AspectListExecutor1 aspectListExecutor1 = new AspectListExecutor1(tagetClass, aspectInfo1List);
            Object proxyBean = ProxyCreator.createProxy(tagetClass, aspectListExecutor1);
            beanContainer.addBean(tagetClass,proxyBean);
        }
    }

    // 2.将切面类按照不同的拦截controller目前进行切分
    private void categorizeAspect(Map<Class<? extends Annotation>, List<AspectInfo1>> categorizedMap, Class<?> aspectClass) {
        Order orderAnnotation = aspectClass.getAnnotation(Order.class);
        Aspect1 aspectAnnotation = aspectClass.getAnnotation(Aspect1.class);
        DefaultAspect aspect = (DefaultAspect)beanContainer.getBean(aspectClass);
        AspectInfo1 aspectInfo1 = new AspectInfo1(orderAnnotation.value(), aspect);
        if (!categorizedMap.containsKey(aspectAnnotation.value())){
            // 不存在就创建
            List<AspectInfo1> aspectInfo1List = new ArrayList<>();
            aspectInfo1List.add(aspectInfo1);
            categorizedMap.put(aspectAnnotation.value(), aspectInfo1List);
        }else{
            // 存在，就取出来添加
            List<AspectInfo1> aspectInfo1List = categorizedMap.get(aspectAnnotation.value());
            aspectInfo1List.add(aspectInfo1);
        }
    }

    // 框架中一定要遵守给Aspect类添加@Aspect和@Order标签的规范，同时，必须遵守继承自DefaultAspect
    // 此外，@Aspect的属性值不能是它本身
    private boolean verifyAspect(Class<?> aspectClass) {
        return (aspectClass.isAnnotationPresent(Aspect1.class) ||
                aspectClass.isAnnotationPresent(Order.class)) &&
                DefaultAspect.class.isAssignableFrom(aspectClass) &&
                aspectClass.getAnnotation(Aspect1.class).value() != Aspect1.class;
    }
}
